home *** CD-ROM | disk | FTP | other *** search
/ Aminet 4 / Aminet 4 - November 1994.iso / aminet / dev / misc / flex_2_4_7.lha / flex-2.4.7misc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-22  |  14.2 KB  |  776 lines

  1. /* misc - miscellaneous flex routines */
  2.  
  3. /*-
  4.  * Copyright (c) 1990 The Regents of the University of California.
  5.  * All rights reserved.
  6.  *
  7.  * This code is derived from software contributed to Berkeley by
  8.  * Vern Paxson.
  9.  * 
  10.  * The United States Government has rights in this work pursuant
  11.  * to contract no. DE-AC03-76SF00098 between the United States
  12.  * Department of Energy and the University of California.
  13.  *
  14.  * Redistribution and use in source and binary forms are permitted provided
  15.  * that: (1) source distributions retain this entire copyright notice and
  16.  * comment, and (2) distributions including binaries display the following
  17.  * acknowledgement:  ``This product includes software developed by the
  18.  * University of California, Berkeley and its contributors'' in the
  19.  * documentation or other materials provided with the distribution and in
  20.  * all advertising materials mentioning features or use of this software.
  21.  * Neither the name of the University nor the names of its contributors may
  22.  * be used to endorse or promote products derived from this software without
  23.  * specific prior written permission.
  24.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  25.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  26.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  27.  */
  28.  
  29. /* $Header: misc.c,v 1.2 94/01/04 14:33:10 vern Exp $ */
  30.  
  31. #include "flexdef.h"
  32.  
  33.  
  34.  
  35. /* declare functions that have forward references */
  36.  
  37. void dataflush PROTO((void));
  38. int otoi PROTO((Char []));
  39. int htoi PROTO((Char str[]));
  40. int is_hex_digit PROTO((int ch));
  41.  
  42.  
  43. void add_action( new_text )
  44. char *new_text;
  45.     {
  46.     int len = strlen( new_text );
  47.  
  48.     while ( len + action_index >= action_size - 10 /* slop */ )
  49.         {
  50.         action_size *= 2;
  51.         action_array =
  52.             reallocate_character_array( action_array, action_size );
  53.         }
  54.  
  55.     strcpy( &action_array[action_index], new_text );
  56.  
  57.     action_index += len;
  58.     }
  59.  
  60.  
  61. /* allocate_array - allocate memory for an integer array of the given size */
  62.  
  63. void *allocate_array( size, element_size )
  64. int size, element_size;
  65.     {
  66.     register void *mem;
  67.  
  68.     /* On 16-bit int machines (e.g., 80286) we might be trying to
  69.      * allocate more than a signed int can hold, and that won't
  70.      * work.  Cheap test:
  71.      */
  72.     if ( element_size * size <= 0 )
  73.         flexfatal( "request for < 1 byte in allocate_array()" );
  74.  
  75.     mem = flex_alloc( element_size * size );
  76.  
  77.     if ( mem == NULL )
  78.         flexfatal( "memory allocation failed in allocate_array()" );
  79.  
  80.     return mem;
  81.     }
  82.  
  83.  
  84. /* all_lower - true if a string is all lower-case */
  85.  
  86. int all_lower( str )
  87. register char *str;
  88.     {
  89.     while ( *str )
  90.         {
  91.         if ( ! isascii( (Char) *str ) || ! islower( *str ) )
  92.             return 0;
  93.         ++str;
  94.         }
  95.  
  96.     return 1;
  97.     }
  98.  
  99.  
  100. /* all_upper - true if a string is all upper-case */
  101.  
  102. int all_upper( str )
  103. register char *str;
  104.     {
  105.     while ( *str )
  106.         {
  107.         if ( ! isascii( (Char) *str ) || ! isupper( *str ) )
  108.             return 0;
  109.         ++str;
  110.         }
  111.  
  112.     return 1;
  113.     }
  114.  
  115.  
  116. /* bubble - bubble sort an integer array in increasing order
  117.  *
  118.  * synopsis
  119.  *   int v[n], n;
  120.  *   void bubble( v, n );
  121.  *
  122.  * description
  123.  *   sorts the first n elements of array v and replaces them in
  124.  *   increasing order.
  125.  *
  126.  * passed
  127.  *   v - the array to be sorted
  128.  *   n - the number of elements of 'v' to be sorted
  129.  */
  130.  
  131. void bubble( v, n )
  132. int v[], n;
  133.     {
  134.     register int i, j, k;
  135.  
  136.     for ( i = n; i > 1; --i )
  137.         for ( j = 1; j < i; ++j )
  138.             if ( v[j] > v[j + 1] )    /* compare */
  139.                 {
  140.                 k = v[j];    /* exchange */
  141.                 v[j] = v[j + 1];
  142.                 v[j + 1] = k;
  143.                 }
  144.     }
  145.  
  146.  
  147. /* check_char - checks a character to make sure it's within the range
  148.  *        we're expecting.  If not, generates fatal error message
  149.  *        and exits.
  150.  */
  151.  
  152. void check_char( c )
  153. int c;
  154.     {
  155.     if ( c >= CSIZE )
  156.         lerrsf( "bad character '%s' detected in check_char()",
  157.             readable_form( c ) );
  158.  
  159.     if ( c >= csize )
  160.         lerrsf( "scanner requires -8 flag to use the character '%s'",
  161.             readable_form( c ) );
  162.     }
  163.  
  164.  
  165.  
  166. /* clower - replace upper-case letter to lower-case */
  167.  
  168. Char clower( c )
  169. register int c;
  170.     {
  171.     return (Char) ((isascii( c ) && isupper( c )) ? tolower( c ) : c);
  172.     }
  173.  
  174.  
  175. /* copy_string - returns a dynamically allocated copy of a string */
  176.  
  177. char *copy_string( str )
  178. register char *str;
  179.     {
  180.     register char *c;
  181.     char *copy;
  182.  
  183.     /* find length */
  184.     for ( c = str; *c; ++c )
  185.         ;
  186.  
  187.     copy = (char *) flex_alloc( (c - str + 1) * sizeof( char ) );
  188.  
  189.     if ( copy == NULL )
  190.         flexfatal( "dynamic memory failure in copy_string()" );
  191.  
  192.     for ( c = copy; (*c++ = *str++); )
  193.         ;
  194.  
  195.     return copy;
  196.     }
  197.  
  198.  
  199. /* copy_unsigned_string -
  200.  *    returns a dynamically allocated copy of a (potentially) unsigned string
  201.  */
  202.  
  203. Char *copy_unsigned_string( str )
  204. register Char *str;
  205.     {
  206.     register Char *c;
  207.     Char *copy;
  208.  
  209.     /* find length */
  210.     for ( c = str; *c; ++c )
  211.         ;
  212.  
  213.     copy = allocate_Character_array( c - str + 1 );
  214.  
  215.     for ( c = copy; (*c++ = *str++); )
  216.         ;
  217.  
  218.     return copy;
  219.     }
  220.  
  221.  
  222. /* cshell - shell sort a character array in increasing order
  223.  *
  224.  * synopsis
  225.  *
  226.  *   Char v[n];
  227.  *   int n, special_case_0;
  228.  *   cshell( v, n, special_case_0 );
  229.  *
  230.  * description
  231.  *   Does a shell sort of the first n elements of array v.
  232.  *   If special_case_0 is true, then any element equal to 0
  233.  *   is instead assumed to have infinite weight.
  234.  *
  235.  * passed
  236.  *   v - array to be sorted
  237.  *   n - number of elements of v to be sorted
  238.  */
  239.  
  240. void cshell( v, n, special_case_0 )
  241. Char v[];
  242. int n, special_case_0;
  243.     {
  244.     int gap, i, j, jg;
  245.     Char k;
  246.  
  247.     for ( gap = n / 2; gap > 0; gap = gap / 2 )
  248.         for ( i = gap; i < n; ++i )
  249.             for ( j = i - gap; j >= 0; j = j - gap )
  250.                 {
  251.                 jg = j + gap;
  252.  
  253.                 if ( special_case_0 )
  254.                     {
  255.                     if ( v[jg] == 0 )
  256.                         break;
  257.  
  258.                     else if ( v[j] != 0 && v[j] <= v[jg] )
  259.                         break;
  260.                     }
  261.  
  262.                 else if ( v[j] <= v[jg] )
  263.                     break;
  264.  
  265.                 k = v[j];
  266.                 v[j] = v[jg];
  267.                 v[jg] = k;
  268.                 }
  269.     }
  270.  
  271.  
  272. /* dataend - finish up a block of data declarations */
  273.  
  274. void dataend()
  275.     {
  276.     if ( datapos > 0 )
  277.         dataflush();
  278.  
  279.     /* add terminator for initialization; { for vi */
  280.     puts( "    } ;\n" );
  281.  
  282.     dataline = 0;
  283.     datapos = 0;
  284.     }
  285.  
  286.  
  287. /* dataflush - flush generated data statements */
  288.  
  289. void dataflush()
  290.     {
  291.     putchar( '\n' );
  292.  
  293.     if ( ++dataline >= NUMDATALINES )
  294.         {
  295.         /* Put out a blank line so that the table is grouped into
  296.          * large blocks that enable the user to find elements easily.
  297.          */
  298.         putchar( '\n' );
  299.         dataline = 0;
  300.         }
  301.  
  302.     /* Reset the number of characters written on the current line. */
  303.     datapos = 0;
  304.     }
  305.  
  306.  
  307. /* flexerror - report an error message and terminate */
  308.  
  309. void flexerror( msg )
  310. char msg[];
  311.     {
  312.     fprintf( stderr, "%s: %s\n", program_name, msg );
  313.     flexend( 1 );
  314.     }
  315.  
  316.  
  317. /* flexfatal - report a fatal error message and terminate */
  318.  
  319. void flexfatal( msg )
  320. char msg[];
  321.     {
  322.     fprintf( stderr, "%s: fatal internal error, %s\n", program_name, msg );
  323.     exit( 1 );
  324.     }
  325.  
  326.  
  327. /* lerrif - report an error message formatted with one integer argument */
  328.  
  329. void lerrif( msg, arg )
  330. char msg[];
  331. int arg;
  332.     {
  333.     char errmsg[MAXLINE];
  334.     (void) sprintf( errmsg, msg, arg );
  335.     flexerror( errmsg );
  336.     }
  337.  
  338.  
  339. /* lerrsf - report an error message formatted with one string argument */
  340.  
  341. void lerrsf( msg, arg )
  342. char msg[], arg[];
  343.     {
  344.     char errmsg[MAXLINE];
  345.  
  346.     (void) sprintf( errmsg, msg, arg );
  347.     flexerror( errmsg );
  348.     }
  349.  
  350.  
  351. /* htoi - convert a hexadecimal digit string to an integer value */
  352.  
  353. int htoi( str )
  354. Char str[];
  355.     {
  356.     unsigned int result;
  357.  
  358.     (void) sscanf( (char *) str, "%x", &result );
  359.  
  360.     return (int)result;
  361.     }
  362.  
  363.  
  364. /* is_hex_digit - returns true if a character is a valid hex digit, false
  365.  *          otherwise
  366.  */
  367.  
  368. int is_hex_digit( ch )
  369. int ch;
  370.     {
  371.     if ( isdigit( ch ) )
  372.         return 1;
  373.  
  374.     switch ( clower( ch ) )
  375.         {
  376.         case 'a':
  377.         case 'b':
  378.         case 'c':
  379.         case 'd':
  380.         case 'e':
  381.         case 'f':
  382.             return 1;
  383.  
  384.         default:
  385.             return 0;
  386.         }
  387.     }
  388.  
  389.  
  390. /* line_directive_out - spit out a "# line" statement */
  391.  
  392. void line_directive_out( output_file )
  393. FILE *output_file;
  394.     {
  395.     if ( infilename && gen_line_dirs )
  396.         {
  397.         char directive[MAXLINE];
  398.         sprintf( directive, "# line %d \"%s\"\n", linenum, infilename );
  399.  
  400.         /* If output_file is nil then we should put the directive in
  401.          * the accumulated actions.
  402.          */
  403.         if ( output_file )
  404.             fputs( directive, output_file );
  405.         else
  406.             add_action( directive );
  407.         }
  408.     }
  409.  
  410.  
  411. /* mark_defs1 - mark the current position in the action array as
  412.  *               representing where the user's section 1 definitions end
  413.  *         and the prolog begins
  414.  */
  415. void mark_defs1()
  416.     {
  417.     defs1_offset = 0;
  418.     action_array[action_index++] = '\0';
  419.     action_offset = prolog_offset = action_index;
  420.     action_array[action_index] = '\0';
  421.     }
  422.  
  423.  
  424. /* mark_prolog - mark the current position in the action array as
  425.  *               representing the end of the action prolog
  426.  */
  427. void mark_prolog()
  428.     {
  429.     action_array[action_index++] = '\0';
  430.     action_offset = action_index;
  431.     action_array[action_index] = '\0';
  432.     }
  433.  
  434.  
  435. /* mk2data - generate a data statement for a two-dimensional array
  436.  *
  437.  * Generates a data statement initializing the current 2-D array to "value".
  438.  */
  439. void mk2data( value )
  440. int value;
  441.     {
  442.     if ( datapos >= NUMDATAITEMS )
  443.         {
  444.         putchar( ',' );
  445.         dataflush();
  446.         }
  447.  
  448.     if ( datapos == 0 )
  449.         /* Indent. */
  450.         fputs( "    ", stdout );
  451.  
  452.     else
  453.         putchar( ',' );
  454.  
  455.     ++datapos;
  456.  
  457.     printf( "%5d", value );
  458.     }
  459.  
  460.  
  461. /* mkdata - generate a data statement
  462.  *
  463.  * Generates a data statement initializing the current array element to
  464.  * "value".
  465.  */
  466. void mkdata( value )
  467. int value;
  468.     {
  469.     if ( datapos >= NUMDATAITEMS )
  470.         {
  471.         putchar( ',' );
  472.         dataflush();
  473.         }
  474.  
  475.     if ( datapos == 0 )
  476.         /* Indent. */
  477.         fputs( "    ", stdout );
  478.     else
  479.         putchar( ',' );
  480.  
  481.     ++datapos;
  482.  
  483.     printf( "%5d", value );
  484.     }
  485.  
  486.  
  487. /* myctoi - return the integer represented by a string of digits */
  488.  
  489. int myctoi( array )
  490. char array[];
  491.     {
  492.     int val = 0;
  493.  
  494.     (void) sscanf( array, "%d", &val );
  495.  
  496.     return val;
  497.     }
  498.  
  499.  
  500. /* myesc - return character corresponding to escape sequence */
  501.  
  502. Char myesc( array )
  503. Char array[];
  504.     {
  505.     Char c, esc_char;
  506.  
  507.     switch ( array[1] )
  508.         {
  509.         case 'b': return '\b';
  510.         case 'f': return '\f';
  511.         case 'n': return '\n';
  512.         case 'r': return '\r';
  513.         case 't': return '\t';
  514.  
  515. #ifdef __STDC__
  516.         case 'a': return '\a';
  517.         case 'v': return '\v';
  518. #else
  519.         case 'a': return '\007';
  520.         case 'v': return '\013';
  521. #endif
  522.  
  523.         case '0':
  524.         case '1':
  525.         case '2':
  526.         case '3':
  527.         case '4':
  528.         case '5':
  529.         case '6':
  530.         case '7':
  531.         case '8':
  532.         case '9':
  533.             { /* \<octal> */
  534.             int sptr = 1;
  535.  
  536.             while ( isascii( array[sptr] ) &&
  537.                 isdigit( array[sptr] ) )
  538.                 /* Don't increment inside loop control
  539.                  * because if isdigit() is a macro it might
  540.                  * expand into multiple increments ...
  541.                  */
  542.                 ++sptr;
  543.  
  544.             c = array[sptr];
  545.             array[sptr] = '\0';
  546.  
  547.             esc_char = otoi( array + 1 );
  548.  
  549.             array[sptr] = c;
  550.  
  551.             return esc_char;
  552.             }
  553.  
  554.         case 'x':
  555.             { /* \x<hex> */
  556.             int sptr = 2;
  557.  
  558.             while ( isascii( array[sptr] ) &&
  559.                 is_hex_digit( (char) array[sptr] ) )
  560.                 /* Don't increment inside loop control
  561.                  * because if isdigit() is a macro it might
  562.                  * expand into multiple increments ...
  563.                  */
  564.                 ++sptr;
  565.  
  566.             c = array[sptr];
  567.             array[sptr] = '\0';
  568.  
  569.             esc_char = htoi( array + 2 );
  570.  
  571.             array[sptr] = c;
  572.  
  573.             return esc_char;
  574.             }
  575.  
  576.         default:
  577.             return array[1];
  578.         }
  579.     }
  580.  
  581.  
  582. /* otoi - convert an octal digit string to an integer value */
  583.  
  584. int otoi( str )
  585. Char str[];
  586.     {
  587.     unsigned int result;
  588.  
  589.     (void) sscanf( (char *) str, "%o", &result );
  590.     return (int)result;
  591.     }
  592.  
  593.  
  594. /* readable_form - return the the human-readable form of a character
  595.  *
  596.  * The returned string is in static storage.
  597.  */
  598.  
  599. char *readable_form( c )
  600. register int c;
  601.     {
  602.     static char rform[10];
  603.  
  604.     if ( (c >= 0 && c < 32) || c >= 127 )
  605.         {
  606.         switch ( c )
  607.             {
  608.             case '\b': return "\\b";
  609.             case '\f': return "\\f";
  610.             case '\n': return "\\n";
  611.             case '\r': return "\\r";
  612.             case '\t': return "\\t";
  613.  
  614. #ifdef __STDC__
  615.             case '\a': return "\\a";
  616.             case '\v': return "\\v";
  617. #endif
  618.  
  619.             default:
  620.                 (void) sprintf( rform, "\\%.3o",
  621.                         (unsigned int) c );
  622.                 return rform;
  623.             }
  624.         }
  625.  
  626.     else if ( c == ' ' )
  627.         return "' '";
  628.  
  629.     else
  630.         {
  631.         rform[0] = c;
  632.         rform[1] = '\0';
  633.  
  634.         return rform;
  635.         }
  636.     }
  637.  
  638.  
  639. /* reallocate_array - increase the size of a dynamic array */
  640.  
  641. void *reallocate_array( array, size, element_size )
  642. void *array;
  643. int size, element_size;
  644.     {
  645.     register void *new_array;
  646.  
  647.     /* Same worry as in allocate_array(): */
  648.     if ( size * element_size <= 0 )
  649.         flexfatal(
  650.             "attempt to increase array size by less than 1 byte" );
  651.  
  652.     new_array = flex_realloc( array, size * element_size );
  653.  
  654.     if ( new_array == NULL )
  655.         flexfatal( "attempt to increase array size failed" );
  656.  
  657.     return new_array;
  658.     }
  659.  
  660.  
  661. /* skelout - write out one section of the skeleton file
  662.  *
  663.  * Description
  664.  *    Copies skelfile or skel array to stdout until a line beginning with
  665.  *    "%%" or EOF is found.
  666.  */
  667. void skelout()
  668.     {
  669.     char buf_storage[MAXLINE];
  670.     char *buf = buf_storage;
  671.     int do_copy = 1;
  672.  
  673.     /* Loop pulling lines either from the skelfile, if we're using
  674.      * one, or from the skel[] array.
  675.      */
  676.     while ( skelfile ?
  677.         (fgets( buf, MAXLINE, skelfile ) != NULL) :
  678.         ((buf = skel[skel_ind++]) != 0) )
  679.         { /* copy from skel array */
  680.         if ( buf[0] == '%' )
  681.             { /* control line */
  682.             switch ( buf[1] )
  683.                 {
  684.                 case '%':
  685.                     return;
  686.  
  687.                 case '+':
  688.                     do_copy = C_plus_plus;
  689.                     break;
  690.  
  691.                 case '-':
  692.                     do_copy = ! C_plus_plus;
  693.                     break;
  694.  
  695.                 case '*':
  696.                     do_copy = 1;
  697.                     break;
  698.  
  699.                 default:
  700.                     flexfatal(
  701.                         "bad line in skeleton file" );
  702.                 }
  703.             }
  704.  
  705.         else if ( do_copy )
  706.             {
  707.             if ( skelfile )
  708.                 /* Skeleton file reads include final
  709.                  * newline, skel[] array does not.
  710.                  */
  711.                 fputs( buf, stdout );
  712.             else
  713.                 printf( "%s\n", buf );
  714.             }
  715.         }
  716.     }
  717.  
  718.  
  719. /* transition_struct_out - output a yy_trans_info structure
  720.  *
  721.  * outputs the yy_trans_info structure with the two elements, element_v and
  722.  * element_n.  Formats the output with spaces and carriage returns.
  723.  */
  724.  
  725. void transition_struct_out( element_v, element_n )
  726. int element_v, element_n;
  727.     {
  728.     printf( "%7d, %5d,", element_v, element_n );
  729.  
  730.     datapos += TRANS_STRUCT_PRINT_LENGTH;
  731.  
  732.     if ( datapos >= 75 )
  733.         {
  734.         putchar( '\n' );
  735.  
  736.         if ( ++dataline % 10 == 0 )
  737.             putchar( '\n' );
  738.  
  739.         datapos = 0;
  740.         }
  741.     }
  742.  
  743.  
  744. /* The following is only needed when building flex's parser using certain
  745.  * broken versions of bison.
  746.  */
  747. void *yy_flex_xmalloc( size )
  748. int size;
  749.     {
  750.     void *result = flex_alloc( size );
  751.  
  752.     if ( ! result  )
  753.         flexfatal( "memory allocation failed in yy_flex_xmalloc()" );
  754.  
  755.     return result;
  756.     }
  757.  
  758.  
  759. /* zero_out - set a region of memory to 0
  760.  *
  761.  * Sets region_ptr[0] through region_ptr[size_in_bytes - 1] to zero.
  762.  */
  763.  
  764. void zero_out( region_ptr, size_in_bytes )
  765. char *region_ptr;
  766. int size_in_bytes;
  767.     {
  768.     register char *rp, *rp_end;
  769.  
  770.     rp = region_ptr;
  771.     rp_end = region_ptr + size_in_bytes;
  772.  
  773.     while ( rp < rp_end )
  774.         *rp++ = 0;
  775.     }
  776.